package org.os.framework.document.swagger;

import java.util.Arrays;

import javax.annotation.Resource;

import org.os.framework.document.swagger.entity.SwaggerProps;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.util.AntPathMatcher;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.OperationBuilderPlugin;
import springfox.documentation.spi.service.contexts.OperationContext;
import springfox.documentation.swagger.common.SwaggerPluginSupport;

/**
 * swagger插件
 * 
 * @author
 */
@Slf4j
@Data
@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1)
@Configuration
public class RequiredToken implements OperationBuilderPlugin {

    private final AntPathMatcher pathMatcher = new AntPathMatcher();

    @Resource
    private SwaggerProps props;

    @Override
    public boolean supports(DocumentationType documentationType) {
        return DocumentationType.SWAGGER_2.equals(documentationType);
    }

    @Override
    public void apply(OperationContext context) {
        HttpMethod method = context.httpMethod();
        String pattern = context.requestMappingPattern();
        if (null == pattern || "".equals(pattern.trim())) {
            return;
        }
        boolean isOpened = props.getRequestHandlerTokenFilter()
                .stream()
                .anyMatch(f -> (pathMatcher.match(f.getMethod(), method.name()))
                        && pathMatcher.match(f.getUrl(), pattern));
        if (isOpened) {
            log.info("已启用token验证: {} {}", method, pattern);
            // 方法需要Token验证，添加Token参数
            ParameterBuilder tokenPar = new ParameterBuilder();
            tokenPar.name(props.getRequestHandlerTokenField())
                    .description(props.getRequestHandlerTokenDescription())
                    .modelRef(new ModelRef(props.getRequestHandlerTokenType()))
                    .parameterType(props.getRequestHandlerTokenParameterType())
                    .required(true)
                    .build();
            context.operationBuilder().parameters(Arrays.asList(tokenPar.build()));
        }
    }

}
